

package com.lemon.cloud.oauth.config;

import com.lemon.cloud.oauth.support.core.FormIdentityLoginConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer;
import org.springframework.security.web.SecurityFilterChain;

/**
 * 服务安全相关配置
 *
 * @author huangds
 * @date 2022/1/12
 */
@EnableWebSecurity
public class WebSecurityConfiguration {

	@Value("${spring.application.name}")
	private String applicationName;

	/**
	 * spring security 默认的安全策略
	 * @param http security注入点
	 * @return SecurityFilterChain
	 * @throws Exception
	 */
	@Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeRequests(authorizeRequests -> authorizeRequests.requestMatchers("/oauth2/*")
			.permitAll()// 开放自定义的部分端点
			.anyRequest()
			.authenticated())
			.headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin))
			// 表单登录个性化
			.with(new FormIdentityLoginConfig(applicationName), Customizer.withDefaults());
		// 处理 UsernamePasswordAuthenticationToken
		return http.build();
	}

	/**
	 * 暴露静态资源
	 *
	 * https://github.com/spring-projects/spring-security/issues/10938
	 * @param http
	 * @return
	 * @throws Exception
	 */
	@Bean
	@Order(0)
    SecurityFilterChain resources(HttpSecurity http) throws Exception {
		http.securityMatchers((matchers) -> matchers.requestMatchers("/actuator/**", "/static/css/**", "/error"))
			.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll())
			.requestCache(RequestCacheConfigurer::disable)
			.securityContext(AbstractHttpConfigurer::disable)
			.sessionManagement(AbstractHttpConfigurer::disable);
		return http.build();
	}

}
